{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import scipy.io as sio\n",
    "\n",
    "from sklearn.metrics import accuracy_score\n",
    "from sklearn.metrics import roc_auc_score\n",
    "\n",
    "from sklearn.cluster import KMeans\n",
    "from sklearn.svm import SVC\n",
    "\n",
    "from sklearn.model_selection import train_test_split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# load mat\n",
    "mmat= sio.loadmat(\"sample_data.mat\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_data= mmat['test_data']\n",
    "test_target= mmat['test_target']\n",
    "train_data= mmat['train_data']\n",
    "train_target= mmat['train_target']\n",
    "\n",
    "train_target= train_target.T\n",
    "test_target= test_target.T"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "numpy.ndarray"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(train_data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(400, 5)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_target.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Performing clustering:1/5\n",
      "Performing clustering:2/5\n",
      "Performing clustering:3/5\n",
      "Performing clustering:4/5\n",
      "Performing clustering:5/5\n",
      "Building classifiers: :1/5\n",
      "Building classifiers: :2/5\n",
      "Building classifiers: :3/5\n",
      "Building classifiers: :4/5\n",
      "Building classifiers: :5/5\n",
      "Predicting: :1/5\n",
      "The accuracy is: 0.880000\n",
      "Predicting: :2/5\n",
      "The accuracy is: 0.785000\n",
      "Predicting: :3/5\n",
      "The accuracy is: 0.700000\n",
      "Predicting: :4/5\n",
      "The accuracy is: 0.840000\n",
      "Predicting: :5/5\n",
      "The accuracy is: 0.835000\n"
     ]
    }
   ],
   "source": [
    "ratio= 0.1\n",
    "\n",
    "def mLIFT(train_data,train_target,test_data,test_target,ratio):\n",
    "    num_train, dim= train_data.shape\n",
    "    num_test, num_class= test_target.shape\n",
    "    \n",
    "    P_Centers= []\n",
    "    N_Centers= []\n",
    "    \n",
    "    ##### KMeans, and save the centers\n",
    "    for i in range(num_class):\n",
    "        print (\"Performing clustering:%d/%d\" %(i+ 1, num_class))\n",
    "    \n",
    "        p_data= train_data[train_target[:,i]== 1]\n",
    "        n_data= train_data[train_target[:,i]== -1]\n",
    "    \n",
    "        k1= int(min( math.ceil(p_data.shape[0]* ratio), math.ceil(n_data.shape[0]* ratio) ))\n",
    "        #print(\"k1= k2= %d\" %k1)\n",
    "        k2= k1;\n",
    "    \n",
    "        if(k1== 0):\n",
    "            POS_C=[]\n",
    "            zero_kmeans= KMeans(n_clusters= min(50, num_train)).fit(train_data)\n",
    "            NEG_C= zero_kmeans.cluster_centers_\n",
    "        else:\n",
    "            # Positive\n",
    "            if(p_data.shape[0]== 1):\n",
    "                POS_C= p_data\n",
    "            else:\n",
    "                p_kmeans= KMeans(n_clusters= k1).fit(p_data)\n",
    "                POS_C= p_kmeans.cluster_centers_\n",
    "            # Negative\n",
    "            if(n_data.shape[0]== 1):\n",
    "                NEG_C= n_data\n",
    "            else:\n",
    "                n_kmeans= KMeans(n_clusters= k2).fit(n_data)\n",
    "                NEG_C= n_kmeans.cluster_centers_\n",
    "                \n",
    "        # Save the cluster centers\n",
    "        P_Centers.append(POS_C)\n",
    "        N_Centers.append(NEG_C)\n",
    "            \n",
    "    #print(\"The size of P_Canters is %d\\n\" %len(P_Centers))\n",
    "    \n",
    "    ##### Do the map and save the models\n",
    "    Models= []\n",
    "    for i in range(num_class):\n",
    "        print (\"Building classifiers: :%d/%d\" %(i+ 1, num_class))\n",
    "        centers= np.vstack((P_Centers[i], N_Centers[i]))\n",
    "        num_center= centers.shape[0]\n",
    "        # print(num_center)\n",
    "        data= []\n",
    "    \n",
    "        if(num_center>= 5000):\n",
    "            print(\"Too many cluster center!\")\n",
    "            break\n",
    "        else:\n",
    "            blocksize= 5000- num_center\n",
    "            num_block= int(math.ceil(num_train/ blocksize))\n",
    "            # print(num_block)\n",
    "            \n",
    "            mFirst= True\n",
    "            for j in range(num_block- 1):\n",
    "                print(j)\n",
    "                low= j* blocksize\n",
    "                high= (j+ 1)* blocksize\n",
    "                # Calculate the distance\n",
    "                for k in range(num_center):\n",
    "                    diff= train_data[low:high, :]- centers[k]\n",
    "                    Eu_diff= np.linalg.norm(diff, axis=1)\n",
    "                    if(mFirst== True):\n",
    "                        mFirst= False\n",
    "                        data_temp= Eu_diff\n",
    "                    else:\n",
    "                        data_temp= np.vstack((data_temp, Eu_diff))\n",
    "                    \n",
    "            \n",
    "            low= (num_block- 1)* blocksize\n",
    "            high= num_train\n",
    "            \n",
    "            # Calculate the distance\n",
    "            for j in range(num_center):\n",
    "                diff= train_data[low:high,:]- centers[j]\n",
    "                Eu_diff= np.linalg.norm(diff, axis=1)\n",
    "                if(mFirst== True):\n",
    "                    mFirst= False\n",
    "                    data_temp= Eu_diff\n",
    "                else:\n",
    "                    data_temp= np.vstack((data_temp, Eu_diff))\n",
    "            \n",
    "            data= data_temp.T\n",
    "        \n",
    "        training_instance_matrix= data\n",
    "        training_label_vector= train_target[:,i]\n",
    "    \n",
    "        model_this= SVC(C= 10, probability=True).fit(training_instance_matrix, training_label_vector)\n",
    "        #model_this= LogisticRegression(C= 0.03).fit(training_instance_matrix, training_label_vector)\n",
    "        #model_this= DecisionTreeClassifier().fit(training_instance_matrix, training_label_vector)\n",
    "        #model_this = AdaBoostClassifier(DecisionTreeClassifier(),\n",
    "                         #algorithm=\"SAMME\",\n",
    "                         #n_estimators=50, learning_rate=0.8).fit(training_instance_matrix, training_label_vector)\n",
    "        Models.append(model_this)\n",
    "    \n",
    "    ##### Predict\n",
    "    for i in range(num_class):\n",
    "        print (\"Predicting: :%d/%d\" %(i+ 1, num_class))\n",
    "        centers= np.vstack((P_Centers[i], N_Centers[i]))\n",
    "        num_center= centers.shape[0]\n",
    "        # print(num_center)\n",
    "        data= []\n",
    "    \n",
    "        if(num_center>= 5000):\n",
    "            print(\"Too many cluster center!\")\n",
    "            break\n",
    "        else:\n",
    "            blocksize= 5000- num_center\n",
    "            num_block= int(math.ceil(num_test/ blocksize))\n",
    "            # print(num_block)\n",
    "            \n",
    "            mFirst= True\n",
    "            for j in range(num_block- 1):\n",
    "                print(j)\n",
    "                low= j* blocksize\n",
    "                high= (j+ 1)* blocksize\n",
    "                # Calculate the distance\n",
    "                for k in range(num_center):\n",
    "                    diff= test_data[low:high, :]- centers[k]\n",
    "                    Eu_diff= np.linalg.norm(diff, axis=1)\n",
    "                    if(mFirst== True):\n",
    "                        mFirst= False\n",
    "                        data_temp= Eu_diff\n",
    "                    else:\n",
    "                        data_temp= np.vstack((data_temp, Eu_diff))\n",
    "                    \n",
    "            \n",
    "            low= (num_block- 1)* blocksize\n",
    "            high= num_train\n",
    "            \n",
    "            # Calculate the distance\n",
    "            for j in range(num_center):\n",
    "                diff= test_data[low:high,:]- centers[j]\n",
    "                Eu_diff= np.linalg.norm(diff, axis=1)\n",
    "                if(mFirst== True):\n",
    "                    mFirst= False\n",
    "                    data_temp= Eu_diff\n",
    "                else:\n",
    "                    data_temp= np.vstack((data_temp, Eu_diff))\n",
    "            \n",
    "            data= data_temp.T\n",
    "            # print(data.shape)\n",
    "    \n",
    "        testing_instance_matrix= data;\n",
    "        testing_label_vector= test_target[:, i]\n",
    "    \n",
    "        predicted_label= Models[i].predict(testing_instance_matrix)\n",
    "        \n",
    "        #print (predicted_label)\n",
    "\n",
    "        print(\"The accuracy is: %f\" %accuracy_score(testing_label_vector, predicted_label))\n",
    "        #print(roc_auc_score(testing_label_vector, predicted_label))\n",
    "    \n",
    "    return 1\n",
    "\n",
    "\n",
    "mLIFT(train_data,train_target,test_data,test_target,ratio);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
